﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XMLGener.Interfaces;


namespace XMLGener.Data
{
    /// <summary>
    ///   Class is generating text to output.
    ///   This class represents node from tree in generating process.
    /// Tree structure composed from this nodes truly represents structure
    /// of generated xml strucutre. (eg. in recursive definition defined by 1 node
    /// is represented by some nodes in this strucutre)
    ///   
    /// </summary>
    public class XMLGeneratingItem : XMLGenerCalculatingInterface
    {

        /// <summary>
        /// Source node from definition
        /// </summary>
        public XMLGenerNode sourceNode = null;
        
        /// <summary>
        /// Parent of this node
        /// </summary>
        public XMLGeneratingItem parent = null;

        /// <summary>
        /// 
        /// </summary>
        public decimal generateTotal = 0;
        /// <summary>
        /// 
        /// </summary>
        public decimal generateThisElements = 0;
        /// <summary>
        /// 
        /// </summary>
        public decimal generateThisSubelementsTotal = 0;

        /// <summary>
        /// Creating of this class needs source node and output
        /// </summary>
        /// <param name="sourceNode">template node</param>
        /// <param name="outGenerator">output</param>
        public XMLGeneratingItem(XMLGenerNode sourceNode, XMLOutputGenerator outGenerator)
        {
            this.sourceNode = sourceNode;
            this.outPut = outGenerator;
            //this.itemsLeft = sourceNode.minCountForGenarating;
            xelem = this.sourceNode as XMLGenerElement;
            if (xelem != null)
            {
                elementIsTextNode = (xelem.contentType != XMLGenerElement.TYPE_ONLY_ELEMENTS);
            }
            xtext = this.sourceNode as XMLGenerTextNode;
            xelems = this.sourceNode as XMLGenerElements;
            xrangelem = this.sourceNode as XMLGenerRangeElement;
            
        }

        /// <summary>
        /// How many items need to be generater
        /// </summary>
        public decimal thisItemsLeft = 0;

        /// <summary>
        /// 
        /// </summary>
        public decimal thisTotalReserveLeft = 0;

        /// <summary>
        /// 
        /// </summary>
        public decimal thisMaxReserve = 0;

        /// <summary>
        /// 
        /// </summary>
        public decimal reserveForDistribution = 0;
        
        
        /// <summary>
        /// Actual depth of this item. It is used for
        /// formating xml output.
        /// </summary>
        public int depth = 0;

        
        /// <summary>
        /// Output
        /// </summary>
        private XMLOutputGenerator outPut = null;

        private bool elementIsTextNode = false; 

        /// <summary>
        /// If source node is element type.
        /// </summary>
        private XMLGenerElement xelem = null;

        /// <summary>
        /// If source node is element type.
        /// </summary>
        private XMLGenerElements xelems = null;

        private XMLGenerRangeElement xrangelem = null;

        /// <summary>
        /// 
        /// </summary>
        public static Random rnd = new Random();

        
        /// <summary>
        /// If source node is element type.
        /// </summary>
        private XMLGenerTextNode xtext = null;

        /// <summary>
        /// Indicator child of this elememt were generated. 
        /// It is set from outside. It is used in closing element (see: printElementsEnd() )
        /// (to choose if "/&gt;" or "&lt;/element&gt;" should be used
        /// as closing text)
        /// </summary>
        public bool haschilds = false;

        /// <summary>
        /// 
        /// </summary>
        public decimal generatedCount = 0;

        /// <summary>
        /// Print element header without closing elent.
        /// (eg: &lt;element name="John" surname="Shimith"    ... but unclosed)
        /// </summary>
        public void printElementsHeader()
        {
            generatedCount++;
            haschilds = false;
            if (xtext!=null)
            {
                this.outPut.writeLine(xtext.getGeneratedString());
            }

            if (this.xelem == null)
                return;
           
            this.outPut.write("<" + xelem.name, xelem.depth);
            foreach (XMLGenerAttribute att in xelem.attributes)
            {
                this.outPut.write(" " + att.name + "=\"");
                this.outPut.write(att.getGeneratedString() + "\"");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void closeHeaderForChildren()
        {
            if (this.xelem != null)
                this.outPut.writeLine(">");
        
        }
            
        /// <summary>
        /// Indicator, if this node us in waiting state, until all his
        /// childs will be generated. It used and set from outside.
        /// </summary>
        public bool waitingForChilds = false;

        /// <summary>
        /// Close element. 
        /// </summary>
        public void printElementsEnd()
        {
            //this.itemsLeft--;
            if (xelem == null)
                return;
           if (elementIsTextNode)
            {
                this.outPut.write(">"+xelem.getGeneratedString());
                this.outPut.writeLine("</" + xelem.name + ">");
            }
            else if (haschilds)
            {
                this.outPut.writeLine("</" + xelem.name + ">", xelem.depth);
            }
            else 
                this.outPut.writeLine("/>");
            
            
        }

        /// <summary>
        /// How many child elements will be generated
        /// </summary>
        public decimal childElementsCount = 0;
        
        /// <summary>
        /// How many child elements should be generated at the moment.
        /// </summary>
        public decimal childElementsLeft = 0;

        /// <summary>
        /// Calculate, how many child elements will be generated
        /// </summary>
        public void calculateChildItems()
        {
            this.generateTotal--; // exclude this elements
            if (xtext != null || elementIsTextNode || this.generateTotal < 1)
            {
                this.childElementsCount = 0;
                this.childElementsLeft = 0;
                return;
            }
            if (xrangelem == null)
                return;
            if (this.childs == null)
            {
                this.childs = new List<XMLGeneratingItem>();
                foreach (XMLGenerRangeElement childNode in xrangelem.childNodes)
                {
                    if( childNode == null)
                        continue;
                    
                    XMLGeneratingItem child = new XMLGeneratingItem(childNode,this.outPut);
                    child.parent = this;
                    childs.Add(child);
                }
            }
            try
            {
                // generate random fanout, but total must be in boundaries
                decimal randomFanout = generateRandomFanout();
                this.childElementsCount = randomFanout;
                this.childElementsLeft = randomFanout;
                // generate random value
                decimal divSum = 0;
                decimal minFanout = 0;
                foreach (XMLGeneratingItem it in this.childs)
                {
                    it.randomValue = Convert.ToDecimal(rnd.NextDouble()) * it.maxCurrentReserve;
                    minFanout += it.minCurrentCount;
                    divSum += it.randomValue;
                }
                // distribute reserve to elements by frequencies
                dispatchReserveByRandomDiv(randomFanout - minFanout, divSum, this.childs);
                // update count to get generateTotal in between sum of min and max
                //checkAndSetElementsCount(this.generateTotal - randomFanout, this.childs);
                checkAndSetElementsCount(this.generateTotal, this.childs);

            }
            catch (OverflowException oe)
            {
                xrangelem.logger.addErrorLog(this.GetType().ToString(), "Owerflow error : You are using too big numbers to calculate with.");
                xrangelem.logger.addErrorHintLog(this.GetType().ToString(), "Make sure, that there is no number with more than 14 digits.");
            }
            


        }
        
        private decimal generateRandomFanout()
        { 
            decimal minChilds = xrangelem.sumMinChMixCount;
            decimal maxChilds = xrangelem.sumMaxChMixCount;
            decimal randomFanout = Math.Round(Convert.ToDecimal(rnd.NextDouble()) * (maxChilds - minChilds)) + minChilds;
            bool inBoundaries = false;
            decimal tot=this.generateTotal;
            //int i = 5;
            while (!inBoundaries)
            {
                //tot = this.generateTotal - randomFanout;

                //calculate _maxTotalElemens and _minTotalElemens
                calculateMimMaxForCount(randomFanout);
                if (tot <= _maxTotalElemens && tot >= _minTotalElemens)
                {
                    inBoundaries = true;
                    break;
                }
                
                if (tot > _maxTotalElemens)
                {
                    if (minChilds < randomFanout)
                        minChilds = randomFanout;
                    else
                        minChilds++;
                }
                if (tot < _minTotalElemens)
                {
                    if (maxChilds > randomFanout)
                        maxChilds = randomFanout;
                    else
                        maxChilds--;
                }
                if (maxChilds >= minChilds)
                    randomFanout = Math.Round((maxChilds + minChilds - 1) / 2m);
                if (maxChilds <= minChilds)
                    break;
                //randomFanout = Math.Round(Convert.ToDecimal(rnd.NextDouble()) * (maxChilds - minChilds)) + minChilds;
            }
            //this.generateTotal = tot;
            return randomFanout;
        }

        /// <summary>
        ///  Function checks and modifies "generateThisElements" to get
        ///  totalCount in between sum of min and max;
        /// </summary>
        /// <param name="totalCount"></param>
        /// <param name="list"></param>
        public static void checkAndSetElementsCount(decimal totalCount, List<XMLGeneratingItem> list)
        {
            bool outOfBoundaries = true;
            decimal minsum = 0;
            decimal maxsum = 0;
            int direction = 0;
            bool differentCount;
 
            while (outOfBoundaries)
            {
                minsum = 0;
                maxsum = 0;
                foreach (XMLGeneratingItem n in list)
                {
                    minsum += n.generateThisElements * n.minTotalElemens;
                    maxsum += n.generateThisElements * n.maxTotalElemens;
                }

                if (minsum <= totalCount && maxsum >= totalCount)
                {
                    outOfBoundaries = false;
                    break;
                }

                if (minsum > totalCount)
                {
                    if (direction == 1)
                        break;
                    direction = -1;
                    differentCount = false;
                    foreach (XMLGeneratingItem n in list)
                    {
                        if (n.generateThisElements != n.countForMinTotal)
                            differentCount = true;
                        n.generateThisElements = n.countForMinTotal + Math.Round((n.generateThisElements - n.countForMinTotal) / 2m);
                    }
                    if (!differentCount)
                        break;
                }

                if (maxsum < totalCount)
                {
                    if (direction == -1)
                        break;
                    direction = 1;
                    differentCount = false;
                    foreach (XMLGeneratingItem n in list)
                    {
                        if (n.generateThisElements != n.countForMaxTotal)
                            differentCount = true;
                        n.generateThisElements = n.countForMaxTotal + Math.Round((n.generateThisElements - n.countForMaxTotal) / 2m);
                    }
                    if (!differentCount)
                        break;
                }
            }
            decimal totReserve = totalCount - minsum;
            decimal reserveSum = maxsum - minsum;
            decimal tmpTotRes;
            decimal tmpRes;


            foreach (XMLGeneratingItem n in list)
            {
                tmpRes = n.generateThisElements * (n.maxTotalElemens - n.minTotalElemens);
                if (reserveSum > 0)
                    tmpTotRes = Math.Round(totReserve * tmpRes / reserveSum);
                else
                    tmpTotRes = 0;
                n.generateThisSubelementsTotal = n.generateThisElements * n.minTotalElemens + tmpTotRes;
                totReserve -= tmpTotRes;
                reserveSum -= tmpRes;

                n.thisItemsLeft = n.generateThisElements;
                n.totalReserve = n.maxTotalElemens - n.minTotalElemens;
                n.thisTotalReserveLeft = n.totalReserve * n.thisItemsLeft;
                //n.reserveForDistribution = tmpTotRes; 
                n.reserveForDistribution = n.generateThisSubelementsTotal - n.minTotalElemens * n.thisItemsLeft;
            }

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="reserve"></param>
        /// <param name="rndSum"></param>
        /// <param name="list"></param>
        public static void dispatchReserveByRandomDiv(decimal reserve, decimal rndSum, List<XMLGeneratingItem> list)
        {
            
            decimal countToDispatch = reserve ;
            decimal rndLeft = rndSum;
            decimal tmp;
            foreach (XMLGeneratingItem n in list)
            {
                if (rndLeft > 0)
                    tmp = Math.Round(Convert.ToDecimal(n.randomValue * countToDispatch / rndLeft));
                else
                    tmp = 0;
                n.generateThisElements = tmp +n.minCurrentCount;
                rndLeft -= n.randomValue;
                countToDispatch -= tmp;
                if (countToDispatch <= 0 || countToDispatch <= 0)
                    break;
            }


        }

        /// <summary>
        /// 
        /// </summary>
        public decimal randomValue = 0;
        


        private void calculateMimMaxForCount(decimal count)
        {
            this.calculatingThis = true;
            XMLGeneratingItem.calculateMinMaxElements(this, count, count);
            // decrease min/max total elements, because in this count is 
            // included parent element
            this._maxTotalElemens--;
            this._minTotalElemens--;
            this.calculatingThis = false;
        }

        /// <summary>
        /// Childs of this element
        /// </summary>
        public List<XMLGeneratingItem> childs = null;

        /// <summary>
        /// Get next element for gnerating
        /// </summary>
        /// <returns></returns>
        public XMLGeneratingItem getNextSubElement()
        {
            this.childElementsLeft--;
            if (xtext != null)
            {
                return null;
            }


            if (xelems != null)
            {
                decimal rndIndex = (this.childElementsLeft +1)* Convert.ToDecimal( rnd.NextDouble());
                if (xelems.contentType=="random")
                    for (int i=0;i<this.childs.Count;i++)
                    {
                        rndIndex -= this.childs[i].thisItemsLeft;
                        if (rndIndex < 0)
                        {
                            setTotalForItem(this.childs[i]);
                            return this.childs[i];
                        }
                    }
            }


            foreach (XMLGeneratingItem item in this.childs)
            {
                if (item.thisItemsLeft > 0)
                {
                    setTotalForItem(item);
                    return item;
                }
            }
            this.childElementsLeft = 0;
            return null;
        }

        private void setTotalForItem(XMLGeneratingItem item)
        {
            if (item.thisItemsLeft == 1)
            {
                item.generateTotal = item.reserveForDistribution + item.minTotalElemens;
                item.thisTotalReserveLeft = 0;
                item.reserveForDistribution = 0;
                item.thisItemsLeft = 0;
                return;
            }

            if (item.thisItemsLeft < 1)
            {
                item.reserveForDistribution = 0;
                item.generateTotal = 0;
                item.thisItemsLeft=0;
                return;
            }
            decimal currentCount = Math.Round((item.reserveForDistribution * 2 * Convert.ToDecimal(rnd.NextDouble())) / item.thisItemsLeft, 0);
            item.thisTotalReserveLeft -= item.totalReserve;
            if (currentCount > item.reserveForDistribution)
                currentCount = item.reserveForDistribution;
            if ((item.reserveForDistribution - currentCount) > item.thisTotalReserveLeft)
                currentCount = item.reserveForDistribution - item.thisTotalReserveLeft;
            if (currentCount > item.totalReserve)
                currentCount = item.totalReserve;
            item.reserveForDistribution -= currentCount;
            item.generateTotal = currentCount + item.minTotalElemens;
            item.thisItemsLeft--;
        }



        //------------------------------------------ 
        //------------------------------------------ 
        // calculating min and max possible elements
        //------------------------------------------ 
        //------------------------------------------ 

        /// <summary>
        /// 
        /// </summary>
        /// <param name="el"></param>
        /// <param name="minCountLeft"></param>
        /// <param name="maxCountLeft"></param>
        public static void calculateMinMaxElements(XMLGenerCalculatingInterface el, decimal minCountLeft, decimal maxCountLeft)
        {
            List<XMLGenerCalculatingInterface> list = new List<XMLGenerCalculatingInterface>();
            List<XMLGenerCalculatingInterface> countlist = new List<XMLGenerCalculatingInterface>();
            List<XMLGenerCalculatingInterface> freqlist = new List<XMLGenerCalculatingInterface>();

            foreach (XMLGenerCalculatingInterface n in el.childList)
            {
                if (n == null)
                    continue;
                if (n.useFrequency)
                    freqlist.Add(n);
                else
                    countlist.Add(n);
            }


            list.AddRange(freqlist);
            list.AddRange(countlist);

            //------------------------------------------ 
            // calculate minimum
            //------------------------------------------ 
            
            //dispatch min count to frequency 
            XMLGeneratingItem.dispatchCountToFrequency(minCountLeft, el.sumMinChFreq, freqlist);
            foreach (XMLGenerCalculatingInterface n in countlist)
            {
                n.minCurrentCount = n.minCount;
                n.maxCurrentReserve = n.maxCount - n.minCount;
            }
            //sum minimums
            el.minTotalElemens = 1;

            foreach (XMLGenerCalculatingInterface n in list)
            {
                el.minTotalElemens += n.minCurrentCount * n.minTotalElemens;
                n.countForMinTotal = n.minCurrentCount;
                minCountLeft -= n.minCurrentCount;
            }

            // get minimal count from reserve
            list.Sort(XMLGeneratingItem.minTotalComparer);
            decimal min = 0;
            if (minCountLeft > 0)
                foreach (XMLGenerCalculatingInterface n in list)
                {
                    min = Math.Min(minCountLeft, n.maxCurrentReserve);
                    minCountLeft -= min;
                    n.countForMinTotal += min;
                    el.minTotalElemens += min * n.minTotalElemens;
                    if (minCountLeft < 1)
                        break;
                }


            //------------------------------------------ 
            // calculate maximum
            //------------------------------------------ 
            //calculate max count to frequency 
            XMLGeneratingItem.calculateMaxCountForFrequency(maxCountLeft, freqlist);
            //sum maximums
            el.maxTotalElemens = 1;
            foreach (XMLGenerCalculatingInterface n in list)
            {
                el.maxTotalElemens += n.minCurrentCount * n.maxTotalElemens;
                maxCountLeft -= n.minCurrentCount;
                n.countForMaxTotal = n.minCurrentCount;
            }
            //
            list.Sort(XMLGeneratingItem.maxTotalComparer);
            if (maxCountLeft > 0)
                foreach (XMLGenerCalculatingInterface n in list)
                {
                    min = Math.Min(maxCountLeft, n.maxCurrentReserve);
                    maxCountLeft -= min;
                    n.countForMaxTotal += min;
                    el.maxTotalElemens += min * n.maxTotalElemens;
                    if (maxCountLeft < 1)
                        break;
                }
        }


        /// <summary>
        /// Assign count to frequency value
        /// </summary>
        /// <param name="fanout">Count to dispatch to frequencies</param>
        /// <param name="freqSum">sum of frequencies</param>
        /// <param name="list">list of frequencies</param>
        public static void dispatchCountToFrequency(decimal fanout, decimal freqSum, List<XMLGenerCalculatingInterface> list)
        {
            list.Sort(XMLGeneratingItem.maxFreqComparer);
            decimal countToDispatch = fanout * freqSum / 100;
            decimal freqLeft = freqSum;

            foreach (XMLGenerCalculatingInterface n in list)
            {
                n.minCurrentCount = Math.Round(n.minFrequency / freqLeft * countToDispatch);
                n.maxCurrentReserve = Math.Round(n.maxFrequency * fanout) - n.minCurrentCount;
                freqLeft -= n.minFrequency;
                countToDispatch -= n.minCurrentCount;
                if (countToDispatch <= 0 || countToDispatch <= 0)
                    break;
            }


        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fanout"></param>
        /// <param name="list"></param>
        public static void calculateMaxCountForFrequency(decimal fanout, List<XMLGenerCalculatingInterface> list)
        {
            foreach (XMLGenerCalculatingInterface n in list)
            {
                n.minCurrentCount = Math.Round(n.minFrequency * fanout / 100);
                n.maxCurrentReserve = Math.Round(n.maxFrequency * fanout / 100) - n.minCurrentCount;

            }
        }

        private static MinTotalComparer minTotalComparer = new MinTotalComparer();
        private static MaxTotalComparer maxTotalComparer = new MaxTotalComparer();
        private static MaxFreqComparer maxFreqComparer = new MaxFreqComparer();
        private class MinTotalComparer : IComparer<XMLGenerCalculatingInterface>
        {

            #region IComparer<XMLGenerCalculatingInterface> Members
            /// <summary>
            /// 
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public int Compare(XMLGenerCalculatingInterface x, XMLGenerCalculatingInterface y)
            {
                return y.minTotalElemens.CompareTo(x.minTotalElemens);
            }

            #endregion
        }

        private class MaxTotalComparer : IComparer<XMLGenerCalculatingInterface>
        {

            #region IComparer<XMLGenerCalculatingInterface> Members
            /// <summary>
            /// 
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public int Compare(XMLGenerCalculatingInterface x, XMLGenerCalculatingInterface y)
            {
                return y.maxTotalElemens.CompareTo(x.maxTotalElemens);
            }

            #endregion
        }


        private class MaxFreqComparer : IComparer<XMLGenerCalculatingInterface>
        {

            #region IComparer<XMLGenerCalculatingInterface> Members
            /// <summary>
            /// 
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public int Compare(XMLGenerCalculatingInterface x, XMLGenerCalculatingInterface y)
            {
                return y.maxFrequency.CompareTo(x.maxFrequency);
            }

            #endregion
        }



      
        /// <summary>
        /// 
        /// </summary>
        public virtual bool useFrequency
        {
            get {return this.xrangelem.useFrequency; }
            set { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMinChFreq
        {
            get { return this.xrangelem.sumMinChFreq; }
            set {throw new NotImplementedException();}
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMaxChFreq
        {
            get { return this.xrangelem.sumMaxChFreq; }
            set { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMinChCount
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMaxChCount
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual bool chUsesCount
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual bool chUsesFreq
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMaxChMixCount
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        /// <summary>
        /// 
        /// </summary>
        public virtual decimal sumMinChMixCount
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        private decimal _minCurrentCount=0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal minCurrentCount
        {
            get { return this._minCurrentCount; }
            set { this._minCurrentCount = value ; }
        }
        private decimal _maxCurrentReserve=0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal maxCurrentReserve
        {
            get { return this._maxCurrentReserve; }
            set { this._maxCurrentReserve = value; }
        }

        private bool calculatingThis = false;

        private decimal _minTotalElemens = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal minTotalElemens
        {
            get {
                if (this.calculatingThis)
                    return _minTotalElemens;
                return this.xrangelem.minTotalElemens; }
            set { _minTotalElemens = value; }
        }

        private decimal _maxTotalElemens = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal maxTotalElemens
        {
            get {
                if (this.calculatingThis)
                    return _maxTotalElemens;
                return this.xrangelem.maxTotalElemens; }
            set { _maxTotalElemens = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public decimal totalReserve = 0;

        /// <summary>
        /// 
        /// </summary>
        public virtual decimal minFrequency
        {
            get { return  this.xrangelem.minFrequency; }
            set { throw new NotImplementedException(); }
        }

        /// <summary>
        /// 
        /// </summary>
        public virtual decimal maxFrequency
        {
            get { return this.xrangelem.maxFrequency; }
            set { throw new NotImplementedException(); }
        }

        private List<XMLGenerCalculatingInterface> _childList = null;
        /// <summary>
        /// 
        /// </summary>
        public virtual List<XMLGenerCalculatingInterface> childList
        {
            get {
                if (_childList == null)
                {
                    this._childList = new List<XMLGenerCalculatingInterface>();
                    foreach (XMLGeneratingItem n in this.childs)
                    {
                        _childList.Add(n);
                    }
                
                }
                return this._childList; 
            }
        }

        private decimal _countForMinTotal = 0;

        /// <summary>
        /// 
        /// </summary>
        public virtual decimal countForMinTotal
        {
            get { return _countForMinTotal; }
            set { _countForMinTotal = value; }
        }

        private decimal _countForMaxTotal = 0;
        /// <summary>
        /// 
        /// </summary>
        public virtual decimal countForMaxTotal
        {
            get { return _countForMaxTotal; }
            set { this._countForMaxTotal = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public virtual int minCount
        {
            get { return this.xrangelem.minCount; }
            set { throw new NotImplementedException(); }
        }
        /// <summary>
        /// 
        /// </summary>
        public virtual int maxCount
        {
            get { return this.xrangelem.maxCount; }
            set { throw new NotImplementedException(); }
        }

  
    }

    

}
